package com.jf.anmocker.plugin.mockcore.javassist

import com.jf.anmocker.plugin.injector.AnoEntity
import com.jf.anmocker.plugin.injector.InjectEntity
import javassist.ClassPool
import javassist.NotFoundException
import org.objectweb.asm.ClassReader
import java.io.File
import java.io.IOException
import java.io.InputStream

/**
 * @Class: ClassMocker
 * @Description:
 * @author:
 * @Date: 2022/9/27
 */
class AMClassMocker(var mClassPool : ClassPool) {

    private val methodMocker = MethodMockerManager(mClassPool)

    fun injectClass(drtAbsPath : String, file : File, anoList : MutableList<AnoEntity>?){
        if (!file.path.endsWith(".class")) {
            println("injectClass jump: ${file.path}")
            return
        }
        if (file.path.endsWith("/R.class")) {
            println("injectClass jump: ${file.path}")
            return
        }
        // 获取文件流
        var inputStream: InputStream? = null
        try {
            inputStream = file.inputStream()
            // 读取类信息
            val reader = ClassReader(inputStream)
            val className = reader.className.replace('/', '.')
            val tempCls = mClassPool[className]
            // 可以通过下面这些方法获取这个类的更多信息：
            // val annotations = tempCls.annotations
            // val methods = tempCls.methods;
            // val nestedClasses = tempCls.nestedClasses
            // val constructors = tempCls.constructors
            // val declaredClasses = tempCls.declaredClasses
            // val declaringClass = tempCls.declaringClass
            var hasModified = false
            // 遍历这个类定义的所有方法
            if(anoList != null){
                hasModified =  methodMocker.mockerClassMethods(tempCls, anoList)
            }
            // 如果这个类有修改，把新的类写入文件
            if (hasModified) {
                tempCls.writeFile(drtAbsPath)
            }
        } catch (e: IOException) {
            e.printStackTrace()
        } catch (e: NotFoundException) {
            e.printStackTrace()
        }finally {
            inputStream?.close()
        }
    }

    fun injectClass(entity : InjectEntity, anoList : MutableList<AnoEntity>) {
        if (entity.ctClass == null) {
            println("injectClass jump: ctClass is null")
            return
        }
        try {
            // 获取目标类
            val ctClass = entity.ctClass!!
            // 读取类信息
            println("injectClass start >>> ${ctClass.simpleName}")
            // 可以通过下面这些方法获取这个类的更多信息：
            // val annotations = tempCls.annotations
            // val methods = tempCls.methods;
            // val nestedClasses = tempCls.nestedClasses
            // val constructors = tempCls.constructors
            // val declaredClasses = tempCls.declaredClasses
            // val declaringClass = tempCls.declaringClass
            // 遍历这个类定义的所有方法
            val hasModified = methodMocker.mockerClassMethods(ctClass, anoList)
            // 如果这个类有修改，把新的类写入文件
            if (hasModified) {
                ctClass.writeFile(entity.classRootPath)
                println("injectClass success >>> writeFile >>> ${entity.classRootPath}")
            }
            ctClass.detach()
        } catch (e: IOException) {
            e.printStackTrace()
        } catch (e: NotFoundException) {
            e.printStackTrace()
        }
    }
}